package com.gcloud.mesh.dcs.strategy;

import java.io.Serializable;
import java.net.URL;
import java.util.List;
import java.util.UUID;

import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.constant.DictCode;
import org.jeecg.common.exception.MyBusinessException;
import org.jeecg.common.exception.ParamException;
import org.jeecg.common.system.vo.DictModel;
import org.jeecg.modules.system.mapper.SysDictMapper;
import org.springframework.beans.factory.annotation.Autowired;

import com.gcloud.mesh.asset.dao.DatacenterDao;
import com.gcloud.mesh.asset.entity.DatacenterEntity;
import com.gcloud.mesh.asset.service.ICloudResourceService;
import com.gcloud.mesh.config.DnsConfig;
import com.gcloud.mesh.dcs.dao.AppDao;
import com.gcloud.mesh.dcs.dao.SchedulerImagineDao;
import com.gcloud.mesh.dcs.entity.AppEntity;
import com.gcloud.mesh.dcs.entity.SchedulerJobEntity;
import com.gcloud.mesh.dcs.service.SchedulerService;
import com.gcloud.mesh.dcs.strategy.process.ClusterMigrationProcess;
import com.gcloud.mesh.framework.core.SpringUtil;
import com.gcloud.mesh.header.exception.SchedulerErrorCode;
import com.gcloud.mesh.header.vo.restvelero.RestveleroRestoreReply;
import com.gcloud.mesh.monitor.service.StatisticsCheatService;
import com.gcloud.mesh.sdk.RestveleroSDK;
import com.gcloud.mesh.supplier.dao.SupplierDao;
import com.gcloud.mesh.supplier.enums.K8sClusterType;
import com.gcloud.mesh.supplier.enums.SystemType;
import com.gcloud.mesh.utils.DnsUtil;

import lombok.extern.slf4j.Slf4j;

/**
 * k8s集群迁移
 */
//@Component
@Slf4j
public class ClusterMigrationStrategy implements ServerMigrationStrategy {

    @Autowired
    private DatacenterDao datacenterDao;

    @Autowired
    private SupplierDao supplierDao;

    @Autowired
    private AppDao appDao;

    @Autowired
    private SysDictMapper sysDictMapper;

    @Autowired
    private SchedulerService schedulerService;

    @Autowired
    private ICloudResourceService cloudResourceService;

    @Autowired
    private SchedulerImagineDao schedulerImagineDao;

    @Autowired
    private StatisticsCheatService statisticsCheatService;

    @Autowired
    private RestveleroSDK restveleroSDK;

    @Autowired
    private ClusterMigrationProcess clusterMigrationProcess;


    @Override
    public Object doMigration(Serializable p) {
        SchedulerJobEntity job = (SchedulerJobEntity)p;

        DatacenterEntity srcDatacenter = datacenterDao.getById(job.getSrcDatacenterId());
        if (srcDatacenter == null) {
            log.error("[schedule] 数据中心调度,原数据中心{}不存在,id:{}", job.getSrcDatacenterId(), job.getId());
            throw new ParamException(SchedulerErrorCode.SRCDATACENTER_NOT_EXIST);
        }

        DatacenterEntity dstDatacenter = datacenterDao.getById(job.getDstDatacenterId());
        if (dstDatacenter == null) {
            log.error("[schedule] 数据中心调度,目标数据中心{}不存在,id:{}", job.getDstDatacenterId(), job.getId());
            throw new ParamException(SchedulerErrorCode.DSTDATACENTER_NOT_EXIST);
        }

        String srcUrl = supplierDao.getConfigValueByDatacenterIdAndConfigName(srcDatacenter.getId(),
                SystemType.K8S.getName(), K8sClusterType.RESTVELERO_IP.getName());
        String dstUrl = supplierDao.getConfigValueByDatacenterIdAndConfigName(dstDatacenter.getId(),
                SystemType.K8S.getName(), K8sClusterType.RESTVELERO_IP.getName());

        if (StringUtils.isBlank(dstUrl)) {
            log.error("[schedule] 数据中心调度,目标数据中心{}不存在,id:{}", job.getDstDatacenterId(), job.getId());
            throw new ParamException(SchedulerErrorCode.DSTDATACENTER_NOT_EXIST);
        }

        log.debug("[schedule] 数据中心调度开始,id:{}, appId:{}", job.getId(), job.getAppId());

        AppEntity app = appDao.getById(job.getAppId());
        if (app == null) {
            log.error("[schedule] 数据中心调度,应用{}不存在,id:{}", job.getAppId(), job.getId());
            throw new ParamException(SchedulerErrorCode.APP_NOT_EXIST);
        }

        boolean errorSwitch = false;
        List<DictModel> isError = sysDictMapper.queryDictItemsByCode(DictCode.SCHEDULER_ERROR_SWITCH.getCode());
        if (isError != null) {
            for (DictModel value : isError) {
                int errorValue = Integer.parseInt(value.getValue());
                errorSwitch = (errorValue == 1) ? true : false;
            }
        }

        String backupName = app.getName() + "-" + UUID.randomUUID().toString() + "-" + job.getAppId();
        String restoreName = null;
        String namespace = app.getName();
        try {
            // 指定namespace备份
            schedulerService.handleSchedulerBackup(job.getId(), srcUrl, backupName, namespace, errorSwitch);

//			List<DictModel> configs = sysDictMapper.queryDictItemsByCode(DictCode.SCHEDULER_STRATEGY_CONFIG.getCode());
//			if (configs != null) {
//				for (DictModel value : configs) {
//					if (Integer.parseInt(value.getValue()) == 0) {
//						schedulerService.handleSchedulerBackupDataDisk(job.getId(), srcUrl, backupName, namespace,
//								errorSwitch);
//					}
//				}
//			}

            schedulerService.handleSchedulerCheckBackup(job.getId(), job.getAppId(), dstUrl, backupName, errorSwitch);

            // 在目标节点恢复备份
            RestveleroRestoreReply resRestore = schedulerService.handleSchedulerRestore(job.getId(), dstUrl, backupName,
                    errorSwitch);

            if (resRestore != null) {
                schedulerService.handleSchedulerCheckRestore(job.getId(), job.getAppId(), dstUrl,
                        resRestore.getMessage().getRestore_name(), errorSwitch);
//				schedulerService.handleSchedulerCheckRestore(job.getId(), job.getAppId(), dstUrl, errorSwitch);
            }


//            CloudResourceItemVo critem = cloudResourceService.detail(app.getCloudResourceId());
//            String sourceNodeId = critem.getNodeId();
//
//            UpdateCloudResourceMsg msg = new UpdateCloudResourceMsg();
//            msg.setId(app.getCloudResourceId());
//            msg.setDatacenterId(dstDatacenter.getId());
//            Map<String, Object> expand = new HashMap<>();
//            expand.put("nodeId", job.getDstNodeId());
//            msg.setExpand(JsonUtil.toJSONObject(expand).toJSONString());
//            cloudResourceService.update(msg);
//
//            ModelType modelType = ModelType.get(SchedulerModelDict.get(job.getSchedulerModel().toString()).name());
//            SchedulerImagineEntity entity = schedulerImagineDao.get(modelType, job.getAppId(), sourceNodeId,
//                    job.getDstNodeId(), SchedulerImagineEntity.class);
//
//            String temperatureStr = statisticsCheatService.latestSample(MonitorMeter.DATACENTER_TEMPERATURE.getMeter(),
//                    dstDatacenter.getId());
//            String distributionBoxVoltageStr = statisticsCheatService
//                    .latestSample(MonitorMeter.DATACENTER_LOAD.getMeter(), dstDatacenter.getId());
//            String datacenterEnergyStr = statisticsCheatService.latestSample(MonitorMeter.DATACENTER_POWER.getMeter(),
//                    dstDatacenter.getId());
//            String businessRespondStr = statisticsCheatService.latestSample(MonitorMeter.APP_RESPOND_TIME.getMeter(),
//                    app.getId());
//
//            Double temperature = Double.parseDouble(temperatureStr);
//            Double distributionBoxVoltage = Double.parseDouble(distributionBoxVoltageStr);
//            Double datacenterEnergy = Double.parseDouble(datacenterEnergyStr);
//            Double businessRespond = Double.parseDouble(businessRespondStr);
//
//            BigDecimal temperatureBeforeb = new BigDecimal(temperature);
//            temperature = temperatureBeforeb.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
//            BigDecimal distributionBoxVoltageBeforeb = new BigDecimal(distributionBoxVoltage);
//            distributionBoxVoltage = distributionBoxVoltageBeforeb.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
//            BigDecimal datacenterEnergyBeforeb = new BigDecimal(datacenterEnergy);
//            datacenterEnergy = datacenterEnergyBeforeb.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
//            BigDecimal businessRespondBeforeb = new BigDecimal(businessRespond);
//            businessRespond = businessRespondBeforeb.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
//
//            if (entity != null) {
//                schedulerImagineDao.updateAfter(entity, temperature, distributionBoxVoltage, datacenterEnergy,
//                        businessRespond);
//            } else {
//                SchedulerImagineEntity schedulerImagineEntity = new SchedulerImagineEntity();
//                schedulerImagineEntity.setId(UUID.randomUUID().toString());
//                schedulerImagineEntity.setAppId(app.getId());
//                schedulerImagineEntity.setSourceNodeId(sourceNodeId);
//                schedulerImagineEntity.setDestNodeId(job.getDstNodeId());
//                schedulerImagineEntity.setModelType(modelType.name());
//                schedulerImagineEntity.setUpdateTime(new Date());
//                schedulerImagineEntity.setBusinessRespond(businessRespond);
//                schedulerImagineEntity.setDistributionBoxVoltage(distributionBoxVoltage);
//                schedulerImagineEntity.setTemperature(temperature);
//                schedulerImagineEntity.setDatacenterEnergy(datacenterEnergy);
//
//                schedulerImagineDao.save(schedulerImagineEntity);
//            }


            clusterMigrationProcess.deleteSrcNameSpace(job.getId(), app.getId(),5);

            //更改dns配置
            try {
				DnsConfig config = SpringUtil.getBean(DnsConfig.class);
				URL url = new URL(dstUrl);
				DnsUtil.addAndRunDnsFile(config.getServer(), config.getDomain(), url.getHost());
			} catch (Exception e) {
				 log.error("[schedule] 数据中心调度更改dnsnamespaceName{}", app.getName(), e);
			}

            // 更新信息
            // cloudResourceService.updateMigrationResult(app.getId(),job.getDstDatacenterId(),job.getDstNodeId(),job.getSchedulerModel().toString());

        } catch (Exception e) {

            // 删除备份
            try {
                if (StringUtils.isNotBlank(backupName)) {
                    restveleroSDK.backupDelete(srcUrl, backupName);
                    log.info("[schedule] 数据中心调度,回滚删除备份id:{}", backupName);
                }
            } catch (Exception error) {
                log.error("[schedule] 数据中心调度,回滚删除备份失败,备份id:{}", backupName, error);
            }

            // 删除恢复
            try {
                if (StringUtils.isNotBlank(restoreName)) {
                    restveleroSDK.restoreDelete(dstUrl, restoreName);
                    log.info("[schedule] 数据中心调度,回滚恢复备份id:{}", backupName);
                }
            } catch (Exception error) {
                log.error("[schedule] 数据中心调度,回滚删除恢复失败,恢复id:{}", restoreName, error);
            }
            throw new MyBusinessException("集群迁移失败");
        }



        return null;
    }

    @Override
    public String getStrategyName() {
        return SystemType.K8S.getName();
    }
}
